package org.log4jeditor.xml.editor.contentassist.attribute;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.log4jconfig.xml.editor.contentassist.AttributeValueContentAssistProcessor;
import org.log4jeditor.xml.editor.AbstractUITestCase;
import org.log4jeditor.xml.editor.WorkbenchTasks;

@SuppressWarnings("restriction")
public class AttributesContentAssistTestCase extends AbstractUITestCase {

	@Before
	public void setup() throws Exception {
		setupEditorConfiguration("log4j-contentassist.xml");
	}
	
	@After
	public void tearDown() throws Exception {
		super.tearDownProject();
	}

	/**
	 * Get the content completion proposals at <code>lineNumber</code>,
	 * <code>columnNumber</code>.
	 * 
	 * @param lineNumber
	 * @param columnNumber
	 * @return
	 * @throws Exception
	 */
	private ICompletionProposal[] getProposals(int offset) throws Exception {
		return new AttributeValueContentAssistProcessor()
				.computeCompletionProposals(sourceViewer, offset);
	}
	
	@Test
	public void testProposalsForLevelValueReturningAllItems() throws Exception {
		int offset = getDocumentOffset(23, 23, "level");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals...", proposals);
		assertEquals("Wrong number of proposals", 8, proposals.length);
		ICompletionProposal proposal = proposals[0];
		assertEquals("Wrong attribute proposal returned.", "OFF", proposal
				.getDisplayString());
	}

	@Test
	public void testProposalsForLevelValueReturningMatchingItems() throws Exception {
		int offset = getDocumentOffset(23, 24, "level");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals...", proposals);
		assertEquals("Wrong number of proposals", 1, proposals.length);
		ICompletionProposal proposal = proposals[0];
		assertEquals("Wrong attribute proposal returned.", "INFO", proposal
				.getDisplayString());
	}

	@Test
	public void testProposalsForLevelValueReturningNoMatchingItem() throws Exception {
		int offset = getDocumentOffset(26, 25, "level");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposal", proposals);
	}
	
	@Test
	public void testProposalsForLevelValueWithMissingLog4jBundle() throws Exception {
		WorkbenchTasks.removeJavaProjectLibrary(javaProject, log4jLibPath, new NullProgressMonitor());
		int offset = getDocumentOffset(23, 23, "level");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposal", proposals);
	}

	@Test
	public void testProposalsForPriorityValueReturningAllItems() throws Exception {
		int offset = getDocumentOffset(39, 26, "priority");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals...", proposals);
		assertEquals("Wrong number of proposals", 5, proposals.length);
		ICompletionProposal proposal = proposals[0];
		assertEquals("Wrong attribute proposal returned.", "FATAL", proposal
				.getDisplayString());
	}

	@Test
	public void testProposalsForPriorityValueReturningMatchingItems() throws Exception {
		int offset = getDocumentOffset(39, 27, "priority");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals...", proposals);
		assertEquals("Wrong number of proposals", 1, proposals.length);
		ICompletionProposal proposal = proposals[0];
		assertEquals("Wrong attribute proposal returned.", "INFO", proposal
				.getDisplayString());
	}

	@Test
	public void testProposalsForPriorityValueReturningNoMatchingItem() throws Exception {
		int offset = getDocumentOffset(42, 28, "priority");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposal", proposals);
	}
	
	@Test
	public void testProposalsForPriorityValueWithMissingLog4jBundle() throws Exception {
		WorkbenchTasks.removeJavaProjectLibrary(javaProject, log4jLibPath, new NullProgressMonitor());
		int offset = getDocumentOffset(39, 26, "priority");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposal", proposals);
	}

	@Test
	public void testProposalsForAppenderClassReturningMatchingItems()
			throws Exception {
		//setupEditorConfiguration("log4j.xml");
		int offset = getDocumentOffset(4, 69, "appender");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals...", proposals);
		assertEquals("Wrong number of proposals", 1, proposals.length);
		ICompletionProposal proposal = proposals[0];
		assertEquals("Wrong attribute proposal returned.",
				"org.apache.log4j.ConsoleAppender", proposal.getDisplayString());
	}

	@Test
	public void testProposalsForAppenderClassReturningAllItems() throws Exception {
		int offset = getDocumentOffset(4, 45, "appender");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals...", proposals);
		assertEquals("Wrong number of proposals", 19, proposals.length);
		ICompletionProposal proposal = proposals[0];
		assertEquals("Wrong attribute proposal returned.",
				"org.apache.log4j.AsyncAppender", proposal.getDisplayString());
		proposal = proposals[18];
		assertEquals("Wrong attribute proposal returned.", "test.TestAppender",
				proposal.getDisplayString());
	}

	@Test
	public void testProposalsForAppenderClassReturningNoMatchingItem() throws Exception {
		int offset = getDocumentOffset(16, 61, "appender");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposal", proposals);
	}

	@Test
	public void testProposalsForAppenderClassWithMissingLog4jBundle() throws Exception {
		WorkbenchTasks.removeJavaProjectLibrary(javaProject, log4jLibPath, new NullProgressMonitor());
		int offset = getDocumentOffset(4, 45, "appender");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposals...", proposals);
	}

	@Test
	public void testProposalsForAppenderRefRefReturningAllItems() throws Exception {
		int offset = getDocumentOffset(31, 28, "appender-ref");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals...", proposals);
		assertEquals("Wrong number of proposals", 3, proposals.length);
	}

	@Test
	public void testProposalsForAppenderRefRefReturningMatchingItems() throws Exception {
		int offset = getDocumentOffset(31, 28, "appender-ref");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals...", proposals);
		assertEquals("Wrong number of proposals", 3, proposals.length);
	}

	@Test
	public void testProposalsForAppenderRefRefReturningNoMatchingItem() throws Exception {
		int offset = getDocumentOffset(27, 29, "appender-ref");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposal", proposals);
	}
	
	@Test
	public void testProposalsForAppenderRefRefWithNoAvailableItem() throws Exception {
		//super.tearDownProject();
		setupEditorConfiguration("log4j-noappender.xml");
		int offset = getDocumentOffset(17, 28, "appender-ref");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposal", proposals);
	}
	
	@Test
	public void testProposalsForAppenderRefRefWithMissingLog4jBundle() throws Exception {
		WorkbenchTasks.removeJavaProjectLibrary(javaProject, log4jLibPath, new NullProgressMonitor());
		int offset = getDocumentOffset(31, 28, "appender-ref");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals...", proposals);
		assertEquals("Wrong number of proposals", 3, proposals.length);
	}

	@Test
	public void testProposalsForLayoutClassReturningAllItems() throws Exception {
		int offset = getDocumentOffset(12, 24, "layout");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals...", proposals);
		assertEquals("Wrong number of proposals", 6, proposals.length);
		assertEquals("Wrong attribute proposal returned.",
				"org.apache.log4j.HTMLLayout", proposals[0]
						.getDisplayString());
		assertEquals("Wrong attribute proposal returned.",
				"test.TestLayout", proposals[5]
						.getDisplayString());
	}

	@Test
	public void testProposalsForLayoutClassReturningMatchingItems() throws Exception {
		int offset = getDocumentOffset(12, 42, "layout");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals...", proposals);
		assertEquals("Wrong number of proposals", 1, proposals.length);
	}

	@Test
	public void testProposalsForLayoutClassReturningNoMatchingItem() throws Exception {
		int offset = getDocumentOffset(18, 48, "layout");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposal", proposals);
	}
	
	@Test
	public void testProposalsForLayoutClassWithMissingLog4jBundle() throws Exception {
		WorkbenchTasks.removeJavaProjectLibrary(javaProject, log4jLibPath, new NullProgressMonitor());
		int offset = getDocumentOffset(12, 24, "layout");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposal", proposals);
	}

	@Test
	public void testProposalsForCategoryNameReturningAllItems() throws Exception {
		int offset = getDocumentOffset(38, 21, "category");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected many proposals", proposals);
		assertTrue("Expected many, many, many proposals", proposals.length > 10);
	}

	@Test
	public void testProposalsForCategoryNameReturningMatchingItems() throws Exception {
		int offset = getDocumentOffset(41, 22, "category");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals", proposals);
		assertEquals("Wrong number of proposals", 3, proposals.length);
	}

	@Test
	public void testProposalsForCategoryNameReturningNoMatchingItem() throws Exception {
		int offset = getDocumentOffset(45, 28, "category");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposal", proposals);
	}

	@Test
	public void testProposalsForCategoryNameWithMissingLog4jBundle() throws Exception {
		WorkbenchTasks.removeJavaProjectLibrary(javaProject, log4jLibPath, new NullProgressMonitor());
		int offset = getDocumentOffset(38, 21, "category");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected many proposals", proposals);
		assertTrue("Still expected some proposals, found" + proposals.length, proposals.length > 0);
	}

	@Test
	public void testProposalsForLoggerNameReturningAllItems() throws Exception {
		int offset = getDocumentOffset(22, 19, "logger");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected many proposals", proposals);
		assertTrue("Expected many, many, many proposals", proposals.length > 10);
	}

	@Test
	public void testProposalsForLoggerNameReturningMatchingItems() throws Exception {
		int offset = getDocumentOffset(25, 20, "logger");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals", proposals);
		assertEquals("Wrong number of proposals", 3, proposals.length);
	}

	@Test
	public void testProposalsForLoggerNameReturningNoMatchingItem() throws Exception {
		int offset = getDocumentOffset(29, 26, "logger");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposal", proposals);
	}

	@Test
	public void testProposalsForLoggerNameWithMissingLog4jBundle() throws Exception {
		WorkbenchTasks.removeJavaProjectLibrary(javaProject, log4jLibPath, new NullProgressMonitor());
		int offset = getDocumentOffset(22, 19, "logger");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected many proposals", proposals);
		assertTrue("Still expected some proposals, found" + proposals.length, proposals.length > 0);
	}

	@Test
	public void testProposalsForConsoleAppenderParamNameReturningAllItems() throws Exception {
		int offset = getDocumentOffset(5, 22, "param");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals", proposals);
		assertEquals("Wrong number of proposals", 5, proposals.length);
	}

	@Test
	public void testProposalsForConsoleAppenderParamNameReturningMatchingItems()
			throws Exception {
		int offset = getDocumentOffset(5, 23, "param");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNotNull("Expected some proposals", proposals);
		assertEquals("Wrong number of proposals", 2, proposals.length);

	}

	@Test
	public void testProposalsForConsoleAppenderParamNameReturningNoMatchingItem() throws Exception {
		int offset = getDocumentOffset(17, 29, "param");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposal", proposals);
	}

	@Test
	public void testProposalsForConsoleAppenderParamInvalidRegion() throws Exception {
		int offset = getDocumentOffset(11, 37, "param");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposal", proposals);
	}

	@Test
	public void testProposalsForConsoleAppenderParamNameWithMissingLog4jBundle() throws Exception {
		WorkbenchTasks.removeJavaProjectLibrary(javaProject, log4jLibPath, new NullProgressMonitor());
		int offset = getDocumentOffset(5, 23, "param");
		ICompletionProposal[] proposals = getProposals(offset);
		assertNull("Expected no proposal", proposals);
	}

	
}
